﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;


namespace UT3Bots.Communications
{
	internal class Message : EventArgs
	{
        
		internal const char MESSAGE_SEPARATOR = '|';
		internal const char MESSAGE_SUBSEPARATOR = ',';
		internal const char MESSAGE_EOL = '@';
		//private static readonly string[] MESSAGE_EOM = new string[] { "\r\n" };
        private static readonly string[] MESSAGE_EOM = new string[] { "\r\n", "EOM" };
        private static string previousGamePartial = String.Empty;
        private static string previousVisualizerPartial = String.Empty;

		private EventMessage _event;
		private InfoMessage _info = InfoMessage.None;
		private string[] _args;
        private string _message;

		#region Properties
		internal EventMessage Event
		{
			get
			{
				return _event;
			}
		}
		internal InfoMessage Info
		{
			get
			{
				return _info;
			}
		}
		internal string[] Arguments
		{
			get
			{
				return _args;
			}
		}
		internal bool IsEvent
		{
			get
			{
				return this._event != EventMessage.STATE;
			}
		}
		#endregion


		internal Message(string message)
		{
			//if (message != "" && message.EndsWith("EOM"))
			//{
				//message = message.Remove(message.Length - 3, 3);
				//Trace.WriteLine(String.Format("UT3RemoteBot.Message.ctor: parsing string {0}.", message), Global.TRACE_NORMAL_CATEGORY);
            _message = message;
				List<string> tokens = new List<string>(message.Split(new char[]{MESSAGE_SEPARATOR},StringSplitOptions.RemoveEmptyEntries));
                //List<string> tokens = new List<string>(message.Split(MESSAGE_SEPARATOR));

				if (tokens.Count > 1)
				{
					_event = tokens[0].GetAsEvent();
					tokens.RemoveAt(0);

					if (_event == EventMessage.STATE)
					{
						//Add the extra info
						_info = tokens[0].GetAsInfo();
						tokens.RemoveAt(0);
					}


					if (tokens.Count() > 0 && tokens[tokens.Count - 1] == "\r\n") tokens.RemoveAt(tokens.Count - 1);
					_args = tokens.ToArray();
				}
			//}
		}


		internal static List<Message> FromGameData(string Data)
		{
            string toParse;
			List<Message> messages = new List<Message>();

            lock (previousGamePartial)
            {
                /*lock (Console.Out)
                {
                    //Console.WriteLine("++1A++" + previousGamePartial);
                }*/
                toParse = previousGamePartial + Data;
                string[] lines = toParse.Split(MESSAGE_EOM, StringSplitOptions.None);
                if (!Data.EndsWith(MESSAGE_EOM[0]) && !Data.EndsWith(MESSAGE_EOM[1]))
                {
                    previousGamePartial = lines[lines.Length - 1];
                    List<string> tmp = lines.ToList<string>();
                    tmp.RemoveAt(lines.Length - 1);
                    lines = tmp.ToArray();
                }
                else
                {
                    previousGamePartial = String.Empty;
                }
                foreach (string line in lines)
                {
                    if (line.Length > 0)
                        messages.Add(new Message(line));
                }
                /*lock (Console.Out)
                {
                    //Console.WriteLine("++1B++" + previousGamePartial);
                }*/
            }

			return messages;
		}

        internal static List<Message> FromVisualizerData(string Data)
        {
            string toParse;
            List<Message> messages = new List<Message>();

            lock (previousVisualizerPartial)
            {
                lock (Console.Out)
                {
                    //Console.WriteLine("++2A++" + previousVisualizerPartial);
                }
                toParse = previousVisualizerPartial + Data;
                string[] lines = toParse.Split(MESSAGE_EOM, StringSplitOptions.None);
                if (!Data.EndsWith(MESSAGE_EOM[0]) && !Data.EndsWith(MESSAGE_EOM[1]))
                {
                    previousVisualizerPartial = lines[lines.Length - 1];
                    List<string> tmp = lines.ToList<string>();
                    tmp.RemoveAt(lines.Length - 1);
                    lines = tmp.ToArray();
                }
                else
                {
                    previousVisualizerPartial = String.Empty;
                }
                foreach (string line in lines)
                {
                    if (line.Length > 0)
                        messages.Add(new Message(line));
                }
                lock (Console.Out)
                {
                    //Console.WriteLine("++2B++" + previousVisualizerPartial);
                }
            }

            return messages;
        }

		internal static string BuildMessage(CommandMessage Command, params string[] Args)
		{
			StringBuilder sb = new StringBuilder();
			sb.Append(Command.GetStringValue());

			foreach (string arg in Args)
			{
				sb.Append(MESSAGE_SEPARATOR);
				sb.Append(arg);
			}
			//sb.Append(MESSAGE_EOL);

			return sb.ToString();
		}
	}
}
